package it.sephiroth.android.library.bottomnavigation; /* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import android.os.SystemClock; import android.support.test.espresso.UiController; import android.support.test.espresso.action.MotionEvents; import android.support.test.espresso.action.Swiper; import android.support.test.espresso.core.deps.guava.base.Preconditions; import android.util.Log; import android.view.MotionEvent; /** * Executes different swipe types to given positions. */ public enum CustomSwipe implements Swiper { /** Swipes quickly between the co-ordinates. */ MEDIUM { @Override public Swiper.Status sendSwipe( UiController uiController, float[] startCoordinates, float[] endCoordinates, float[] precision) { return sendLinearSwipe(uiController, startCoordinates, endCoordinates, precision, SWIPE_MEDIUM_DURATION_MS ); } }; private static final String TAG = CustomSwipe.class.getSimpleName(); /** The number of motion events to send for each swipe. */ private static final int SWIPE_EVENT_COUNT = 10; /** Length of time a "fast" swipe should last for, in milliseconds. */ private static final int SWIPE_MEDIUM_DURATION_MS = 400; private static float[][] interpolate(float[] start, float[] end, int steps) { Preconditions.checkElementIndex(1, start.length); Preconditions.checkElementIndex(1, end.length); float[][] res = new float[steps][2]; for (int i = 1; i < steps + 1; i++) { res[i - 1][0] = start[0] + (end[0] - start[0]) * i / (steps + 2f); res[i - 1][1] = start[1] + (end[1] - start[1]) * i / (steps + 2f); } return res; } private static Swiper.Status sendLinearSwipe( UiController uiController, float[] startCoordinates, float[] endCoordinates, float[] precision, int duration) { Preconditions.checkNotNull(uiController); Preconditions.checkNotNull(startCoordinates); Preconditions.checkNotNull(endCoordinates); Preconditions.checkNotNull(precision); float[][] steps = interpolate(startCoordinates, endCoordinates, SWIPE_EVENT_COUNT); final int delayBetweenMovements = duration / steps.length; MotionEvent downEvent = MotionEvents.sendDown(uiController, startCoordinates, precision).down; try { for (int i = 0; i < steps.length; i++) { if (!MotionEvents.sendMovement(uiController, downEvent, steps[i])) { Log.e(TAG, "Injection of move event as part of the swipe failed. Sending cancel event."); MotionEvents.sendCancel(uiController, downEvent); return Swiper.Status.FAILURE; } long desiredTime = downEvent.getDownTime() + delayBetweenMovements * i; long timeUntilDesired = desiredTime - SystemClock.uptimeMillis(); if (timeUntilDesired > 10) { uiController.loopMainThreadForAtLeast(timeUntilDesired); } } if (!MotionEvents.sendUp(uiController, downEvent, endCoordinates)) { Log.e(TAG, "Injection of up event as part of the swipe failed. Sending cancel event."); MotionEvents.sendCancel(uiController, downEvent); return Swiper.Status.FAILURE; } } finally { downEvent.recycle(); } return Swiper.Status.SUCCESS; } }